﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.SensorServices.Rfid;
using Microsoft.SensorServices.Rfid.Dspi;
using System.IO.SensorServices.Rfid.Client;
using Microsoft.SensorServices.Rfid.Utilities;
using System.IO;

namespace BizTalk.RFID.EventHandlers
{

    /// <summary>
    /// FileSink class is an event handler that can be used with BizTalk RFID Framework. FileSink is extension for EventHandlerBase Class.
    /// This class allows users to store data captured from RFID devices into a file which can later be processed.
    /// 
    /// This Sink take 5 properties
    /// FileName: Is file name to store data
    /// FilePath: Path of file. Should be complete with last delimited character. e.g c:\temp\
    /// FileExtention: Extension for file/files
    /// Unique: If false only 1 file is created with filename, path and extension. If true, one file is created every time we get an event. the file names are path+filename+uniquenumber+extension
    /// Type: Can either be csv for comma delimited file or xml for XML file.
    /// </summary>
    public class FileSink : RfidEventHandlerBase
    {
        static RfidEventHandlerMetadata rfidEhmetadata;

        #region properties
        private string path = defaultPath;
        private string extension = defaultExtension;
        private string filename = defaultFileName;
        private string type = defaultType;
        private string unique = defaultUnique;
        private bool isUnique = false;

        const string defaultPath = "c:\\";
        const string defaultExtension = "txt";
        const string defaultFileName = "FileSink";
        const string defaultType = "csv";
        const string defaultUnique = "false";

        const string paramFilePath = "FilePath";
        const string paramFileExtension = "FileExtension";
        const string paramFileName = "FileName";
        const string paramType = "Type";
        const string paramUnique = "Unique";

        static StreamWriter writer = null;


        #endregion

        /// <summary>
        /// This funtional returns metadata for the FileSink Event Handler.
        /// </summary>
        /// <param name="getVendorExtensionsAlso"></param>
        /// <returns>File Sink Metadata</returns>
        public static RfidEventHandlerMetadata GetEventHandlerMetadata(bool getVendorExtensionsAlso)
        {
            if (rfidEhmetadata == null)
            {
                Dictionary<string, RfidEventHandlerParameterMetadata> metadata = new Dictionary<string, RfidEventHandlerParameterMetadata>();

                metadata.Add(paramFilePath, new RfidEventHandlerParameterMetadata(typeof(string), "File Path for Sink", defaultPath, false));
                metadata.Add(paramFileExtension, new RfidEventHandlerParameterMetadata(typeof(string), "File Extension for Sink", defaultExtension, false));
                metadata.Add(paramFileName, new RfidEventHandlerParameterMetadata(typeof(string), "File Name for Sink", defaultFileName, false));
                metadata.Add(paramType, new RfidEventHandlerParameterMetadata(typeof(string), "File type (csv or XML)", defaultType, false));
                metadata.Add(paramUnique, new RfidEventHandlerParameterMetadata(typeof(string), "Unique files(true or false)", defaultUnique, false));
                rfidEhmetadata = new RfidEventHandlerMetadata("File Sink", metadata);
            }
            return rfidEhmetadata;
 
        }

        /// <summary>
        /// This class is called to initialize the FileSink Event Handler
        /// </summary>
        /// <param name="parameters">parameters</param>
        /// <param name="container">container</param>
        public override void Init(Dictionary<string, object> parameters, RfidProcessContext container)
        {
            #region initialize parameters
            if (parameters != null)
            {
                if (parameters.ContainsKey(paramFilePath))
                    path = (string)parameters[paramFilePath];
                if (parameters.ContainsKey(paramFileExtension))
                    extension = (string)parameters[paramFileExtension];
                if (parameters.ContainsKey(paramFileName))
                    filename = (string)parameters[paramFileName];
                if (parameters.ContainsKey(paramType))
                    type = (string)parameters[paramType];
                if (parameters.ContainsKey(paramUnique))
                    unique = (string)parameters[paramUnique];
                
            }
            else
            {
                path = defaultPath;
                extension = defaultExtension;
                filename = defaultFileName;
                type = defaultType;
                unique = defaultUnique;
            }

            if (Boolean.Parse(unique).Equals(true))
                isUnique=true;
            
            if (!isUnique)
                writer = new System.IO.StreamWriter(new System.IO.FileStream(path+filename+"."+extension, FileMode.Append));

            #endregion        
        }

        /// <summary>
        /// Called for every time a tag read hits the event handler.
        /// </summary>
        /// <param name="tagReadEvent">Tag Read Information</param>
        /// <returns>return tagread</returns>
        [RfidEventHandlerMethod]
        public RfidEventBase HandleTagReadEvent(RfidEventBase tagGenericReadEvent)
        {
            TagReadEvent tagReadEvent = null;
            try
            {
                tagReadEvent = (TagReadEvent)tagGenericReadEvent;          
            }
            catch (Exception exc)
            {
                return null;
            }
            if (tagReadEvent == null)
            {
                return tagReadEvent;
            }
            if (isUnique)
                writer = new System.IO.StreamWriter(new System.IO.FileStream(path+filename+(DateTime.Now.Ticks)+"."+extension, FileMode.Append));


            if (writer != null)
            {
                if (!(type.ToUpper().Equals("XML")))
                {
                    string strData = "" + HexUtilities.HexEncode(tagReadEvent.GetId()) + "," + tagReadEvent.DeviceName + "," + tagReadEvent.Source + "," + tagReadEvent.Time + "," + tagReadEvent.Type;

                    if (tagReadEvent.VendorSpecificData != null && tagReadEvent.VendorSpecificData.Count > 0)
                    {
                        foreach (string key in tagReadEvent.VendorSpecificData.Keys)
                        {
                            strData = strData + "," + key + "=" + tagReadEvent.VendorSpecificData[key];
                        }
                    }
                    writer.WriteLine(strData);
                }
                else
                {
                    string strData = "<TagRead tagid=\"" + HexUtilities.HexEncode(tagReadEvent.GetId()) + "\" devicename=\"" + tagReadEvent.DeviceName + "\" source=\"" + tagReadEvent.Source + "\" time=\"" + tagReadEvent.Time + "\" type=\"" + tagReadEvent.Type + "\"";


                    if (tagReadEvent.VendorSpecificData != null && tagReadEvent.VendorSpecificData.Count > 0)
                    {
                        foreach (string key in tagReadEvent.VendorSpecificData.Keys)
                        {
                            strData = strData + " " + key + "=\"" + tagReadEvent.VendorSpecificData[key]+"\"";
                        }
                    }
                    strData = strData + " />";
                    writer.WriteLine(strData);

                }

            }

            writer.Flush();
            if (isUnique)
                writer.Close();

            return tagReadEvent;
 
        }
        [RfidEventHandlerMethod]
        public RfidEventBase[] HandleTagReadEvent(RfidEventBase[] tagGenericReadEvent)
        {
            foreach (RfidEventBase eventobj in tagGenericReadEvent)
            {
                HandleTagReadEvent(eventobj);
            }
            return tagGenericReadEvent;
        }

        /// <summary>
        /// Called to dispose the object.
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if ((disposing) && writer != null)
                writer.Close();
        }

    }
}
